home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / Target Acquisition Manager / Source / source / AquireTarget.cpp < prev    next >
Encoding:
Text File  |  1999-06-25  |  13.3 KB  |  626 lines  |  [TEXT/CWIE]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    Macintosh Developer Technical Support
  4. #
  5. #    Simple Color QuickDraw Sample Application
  6. #
  7. #    SillyBalls
  8. #
  9. #    SillyBalls.c    -    C Source
  10. #
  11. #    Copyright © 1988 Apple Computer, Inc.
  12. #    All rights reserved.
  13. #
  14. #    Versions:    1.0                    8/88
  15. #
  16. #    Components:    SillyBalls.c        August 1, 1988
  17. #                SillyBalls.make        August 1, 1988
  18. #
  19. #    This is a very simple sample program that demonstrates how to use Color 
  20. #    QuickDraw.  It is about two pages of code, and does nothing more than open
  21. #    a color window and draw randomly colored ovals in the window.
  22. #    
  23. #    The purpose is to show how to get some initial results with Color QuickDraw.
  24. #    It is a complete program and is very short to be as clear as possible.
  25. #    
  26. #    It does not have an Event Loop.  It is not fully functional in the sense that
  27. #    it does not do all the things you would expect a well behaved Macintosh 
  28. #    program to do, like size the window naturally, have an event loop, use menus, 
  29. #    etc.
  30. #
  31. #    See Sample and TESample for the general structure and MultiFinder techniques that
  32. #    we recommend that you use when building a new application.
  33. #
  34. ------------------------------------------------------------------------------*/
  35.  
  36.     
  37. //    Version 1.0:    6/2/88
  38. //                    7/20/88     DJB    Converted to C
  39. //    
  40. //    purpose        To demonstrate a simple color App using Color QuickDraw.
  41. //                        It draws colored balls in a color window, then uses colored
  42. //                        text inverted in the ball.  The ball location and color is Random.
  43. //                        
  44. //                        This program was written by Bo3b Johnson, 1/88.
  45. //                        
  46. //                        The inverted Bob text was a Skippy Blair special concept,
  47. //                        kept for obvious aesthetic reasons.
  48.  
  49. //MW -cut out some other program descriptions.-
  50.  
  51. //MW ** Metrowerks note **
  52. //   All changed code by Metrowerks is commented by "//MW".
  53. //   There is one type of modification to the original source:
  54. //   • Added argument type and return type to function definitions.
  55. //       In order to pass with extended error checking on.
  56. //    
  57. //   8/31/93 JA
  58.  
  59.  
  60. #include <Types.h>
  61. #include <Memory.h>
  62. #include <Quickdraw.h>
  63. #include <Fonts.h>
  64. #include <Events.h>
  65. #include <Menus.h>
  66. #include <Windows.h>
  67. #include <TextEdit.h>
  68. #include <Dialogs.h>
  69. #include <OSUtils.h>
  70. #include <ToolUtils.h>
  71. #include <SegLoad.h>
  72. #include <Sound.h>
  73. #include <QDOffscreen.h>
  74. #include <algorithm>
  75. #include <cmath>
  76. #include <list>
  77.  
  78. #define assert(value) \
  79.     do { if (!(value)) DebugStr("\pfailed"); } while (false)
  80.  
  81. /* Constants */
  82.  
  83. /* Globals */
  84.     
  85. /* Prototypes */
  86.  
  87. // 
  88. //    Main body of program SillyBalls
  89. //
  90.  
  91. template <class T>
  92. inline T abs(T x)
  93.     { return (x > 0) ? x : -x; }
  94.  
  95. // 
  96. //    Initialize everything for the program, make sure we can run
  97. //
  98. extern "C" void AquireTarget(PicHandle inPic, Point* outPoints, UInt32* outCount);
  99.  
  100. inline unsigned char AbsDelta(unsigned char a, unsigned char b)
  101.     {  return (a > b) ? (a - b) : (b - a); }
  102.  
  103. class ZoomRect
  104.     {
  105.     public:
  106.     
  107.         ZoomRect()
  108.             { }
  109.         ZoomRect(const Rect& source, const Point& dest)
  110.             {
  111.             dstPoint = dest;
  112.             drawRect = source;
  113.         
  114.             height = source.bottom - source.top;
  115.             width = source.right - source.left;
  116.             
  117.             // Draw New
  118.             
  119.             PenMode(patXor);
  120.             PenPat(&qd.gray);
  121.             PenSize(4, 4);
  122.  
  123.             FrameRect(&drawRect);
  124.             
  125.             steps = width / 2;
  126.             currentStep = 0;
  127.             
  128.             PenNormal();
  129.             }
  130.         bool NextRect()
  131.             {
  132.             PenMode(patXor);
  133.             PenPat(&qd.gray);
  134.             PenSize(4, 4);
  135.             
  136.             bool done = false;
  137.  
  138.             if (currentStep < steps)
  139.                 {
  140.                 ++currentStep;
  141.                 
  142.                 Rect newRect;
  143.                 
  144.                 // Draw new
  145.                 
  146.                 newRect.top = dstPoint.v * currentStep / steps;
  147.                 newRect.left = dstPoint.h * currentStep / steps;
  148.                 newRect.bottom = height - (height - dstPoint.v) * currentStep / steps;
  149.                 newRect.right = width - (width - dstPoint.h) * currentStep / steps;
  150.             
  151.                 FrameRect(&newRect);
  152.                 
  153.                 // Erase old;
  154.                 FrameRect(&drawRect);
  155.                 drawRect = newRect;
  156.                 }
  157.             else
  158.                 {
  159.                 // Erase Final
  160.                 FrameRect(&drawRect);
  161.                 done = true;
  162.                 }
  163.             PenNormal();
  164.             return done;
  165.             }
  166.         
  167.     private:
  168.         Rect drawRect;
  169.         int steps;
  170.         int currentStep;
  171.         Point dstPoint;
  172.         short height;
  173.         short width;
  174.     };
  175.  
  176. static void ZoomRects(const Rect& source, const Point& dest)
  177.     {
  178.     ZoomRect zoomRect(source, dest);
  179.     while (!zoomRect.NextRect())
  180.         { }
  181.     }
  182.     
  183. class PlaySound
  184.     {
  185.     public:
  186.         PlaySound(const unsigned char* file);
  187.         ~PlaySound();
  188.     private:
  189.         SndChannelPtr    chan;
  190.         short            refNum;
  191.     };
  192.     
  193. PlaySound::PlaySound(const unsigned char* file) :
  194.     chan (NULL)
  195.     {
  196.     OSErr             error;
  197.     
  198.     error = FSOpen(file, 0, &refNum);
  199.     assert (error == noErr);
  200.     
  201.     error = SndNewChannel(&chan, sampledSynth, initStereo, nil);
  202.     assert (error == noErr);
  203.     
  204.     error = SndStartFilePlay(chan, refNum, 0, 0, nil, nil, nil, true);
  205.     assert (error == noErr);
  206.     }
  207.  
  208. PlaySound::~PlaySound()
  209.     {
  210.     OSErr             error;
  211.     
  212.     error = SndStopFilePlay(chan, true);
  213.     assert (error == noErr);
  214.     
  215.     error = SndDisposeChannel(chan, true);
  216.     assert (error == noErr);
  217.     
  218.     FSClose(refNum);
  219.     }
  220.     
  221. struct Hit
  222.     {
  223.     int hitValue;
  224.     Point hitLoc;
  225.     bool isMarked;
  226.     
  227.     Hit() :
  228.         hitValue(0x7FFFFFFF),
  229.         isMarked(false)
  230.         { }
  231.     
  232.     operator < (const Hit& x) const
  233.         { return hitValue > x.hitValue; }
  234.     };
  235.  
  236. typedef std::list<ZoomRect> ZoomList;
  237.     
  238. void AquireTarget(PicHandle inPic, Point* outPoints, UInt32* outCount)
  239.     {
  240.     GWorldPtr oldWorld;
  241.     GDHandle oldDevice;
  242.     GetGWorld(&oldWorld, &oldDevice);
  243.     
  244.     Hit hitArray[5];
  245.     int screenHeight;
  246.     int screenWidth;
  247.     
  248.     CGrafPort port;
  249.     GWorldPtr world;
  250.     
  251.     ZoomList zoomList;
  252.     
  253.     {
  254.     PlaySound busyChild("\pBusy Child.aif");
  255.     
  256.     // start doing work.
  257.         
  258.     const int imageSize = 32;
  259.     
  260.     if (inPic == nil)
  261.         {
  262.         SysBeep(10);
  263.         return;
  264.         }
  265.     
  266.     *outCount = 0;
  267.     
  268.     OSErr error = NewGWorld(&world, 8, &qd.screenBits.bounds, GetCTable(k8IndexedGrayPixelFormat), NULL, useTempMem);
  269.     assert (error == noErr);
  270.         
  271.     PixMap** map = GetGWorldPixMap(world);
  272.     LockPixels(map);
  273.     
  274.     // Extract the useful attributes
  275.     
  276.     unsigned char* baseAddr = (unsigned char*)map[0]->baseAddr;
  277.     int rowBytes = map[0]->rowBytes & 0x3FFF;
  278.     
  279.     screenWidth = qd.screenBits.bounds.right - qd.screenBits.bounds.left;
  280.     screenHeight = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
  281.     int screenBytes = rowBytes * screenHeight;
  282.         
  283.     // Plot the icon and extract
  284.     
  285.     SetGWorld(world, NULL);
  286.     
  287.     Rect rect = { 0, 0, 32, 32 };
  288.     EraseRect(&rect);
  289.     DrawPicture(inPic, &rect);
  290.     
  291.     unsigned char image[imageSize][imageSize + 1];
  292.     unsigned char edgeWeight[imageSize][imageSize];
  293.     
  294.     for (int i = 0; i < imageSize; ++i)
  295.         {
  296.         BlockMove(baseAddr + (rowBytes * i), &image[i], imageSize);
  297.         image[i][imageSize] = image[i][imageSize - 1]; // Replicate edge pixel for edge finder
  298.         }
  299.     
  300.     for (int v = 0; v < imageSize; ++v)
  301.         {
  302.         for (int h = 0; h < imageSize; ++h)
  303.             {
  304.             edgeWeight[v][h] = AbsDelta(image[v][h],image[v][h + 1]);
  305.             }
  306.         }
  307.     
  308.     // Copy the screen to the offscreen
  309.         
  310.     
  311.     CopyBits(&qd.screenBits, (BitMap*)*map, &qd.screenBits.bounds,
  312.         &qd.screenBits.bounds, srcCopy, NULL);
  313.         
  314.     SetGWorld(oldWorld, oldDevice);
  315.  
  316.     unsigned char* srcPtr = baseAddr;
  317.     
  318.     const int worstPossible = 0x7FFFFFFF;
  319.     int worstHit = worstPossible;
  320.     
  321.     // Set the port for drawing
  322.         
  323.     OpenCPort(&port);
  324.     
  325.     int bufferSize = rowBytes / 10;
  326.     
  327.     Rect rectBuffer[250] = {0};
  328.     bool endOnce = false;
  329.     int bufferPos = 0;
  330.     int tailPos = 0;
  331.     
  332.     TextMode(srcXor);
  333.     TextSize(32);
  334.     TextFont(GetSysFont());
  335.     
  336.     // Draw new
  337.     short width = StringWidth("\pScanning For Possible Targets...");
  338.     MoveTo((screenWidth - width) / 2, 100);
  339.     DrawString("\pScanning For Possible Targets...");
  340.     
  341.     for (int count = 0; count < screenBytes; ++count)
  342.         {
  343.         unsigned long acumulate = 0;
  344.         
  345.         for (int sampleV = 0; sampleV < imageSize; ++sampleV)
  346.             {
  347.             for (int sampleH = 0; sampleH < imageSize; ++sampleH)
  348.                 {
  349.                 unsigned char imageDif = AbsDelta(*(srcPtr + (sampleV - (imageSize / 2)) * rowBytes + (sampleH - (imageSize / 2))), image[sampleV][sampleH]);
  350.                 acumulate += edgeWeight[sampleV][sampleH] * imageDif;
  351.                 }
  352.             }
  353.         
  354.         if ((count & 0x0000008F) == 0)
  355.             {
  356.             for (ZoomList::iterator iter(zoomList.begin());
  357.                     iter != zoomList.end();
  358.                     ++iter)
  359.                 {
  360.                 if ((*iter).NextRect()) iter = zoomList.erase(iter);
  361.                 }
  362.             }
  363.             
  364.             
  365.         if ((count & 0x000000FF) == 0)
  366.             {
  367.             
  368.             if ((count & 0x00000FFF) == 0)
  369.                 {
  370.                 short width = StringWidth("\pScanning For Possible Targets...");
  371.                 MoveTo((screenWidth - width) / 2, 100);
  372.                 DrawString("\pScanning For Possible Targets...");
  373.                 }
  374.             
  375.             short vertical = (srcPtr - baseAddr) / rowBytes;
  376.             short horizontal = (srcPtr - baseAddr) % rowBytes;
  377.             
  378.             rectBuffer[bufferPos].top = vertical - 10;
  379.             rectBuffer[bufferPos].left = horizontal - 10;
  380.             rectBuffer[bufferPos].bottom = rectBuffer[bufferPos].top + 20;
  381.             rectBuffer[bufferPos].right = rectBuffer[bufferPos].left + 20;
  382.             
  383.             InvertOval(&rectBuffer[bufferPos]);
  384.             
  385.             if (endOnce || (bufferPos == (bufferSize - 1)))
  386.                 {
  387.                 InvertOval(&rectBuffer[tailPos]);
  388.                 if (++tailPos == bufferSize) tailPos = 0;
  389.                 endOnce = true;
  390.                 }
  391.             if (++bufferPos == bufferSize) bufferPos = 0;
  392.             }
  393.         
  394.         if (acumulate < worstHit)
  395.             {
  396.             short vertical = (srcPtr - baseAddr) / rowBytes;
  397.             short horizontal = (srcPtr - baseAddr) % rowBytes;
  398.             
  399.             bool foundMatch = false;
  400.             int foundIndex = 0;
  401.             
  402.             // Check and see if we already have a local hit...
  403.             for (int i = 0; i < 5; ++i)
  404.                 {
  405.                 if ((abs(hitArray[i].hitLoc.v - vertical) < 16) &&
  406.                     (abs(hitArray[i].hitLoc.h - horizontal) < 16))
  407.                     {
  408.                     foundMatch = true;
  409.                     foundIndex = i;
  410.                     
  411.                     if (acumulate < hitArray[i].hitValue)
  412.                         {
  413.                         hitArray[i].hitValue = acumulate;
  414.                         hitArray[i].hitLoc.v = vertical;
  415.                         hitArray[i].hitLoc.h = horizontal;
  416.                         }
  417.                     break;
  418.                     }
  419.                 }
  420.             if (!foundMatch)
  421.                 {
  422.                 for (int i = 0; i < 5; ++i)
  423.                     {
  424.                     if (hitArray[i].hitValue == worstHit)
  425.                         {
  426.                         foundMatch = true;
  427.                         foundIndex = i;
  428.                         
  429.                         hitArray[i].hitValue = acumulate;
  430.                         hitArray[i].hitLoc.v = vertical;
  431.                         hitArray[i].hitLoc.h = horizontal;
  432.                         hitArray[i].isMarked = false;
  433.                         break;
  434.                         }
  435.                     }
  436.                 }
  437.                         
  438.             if (foundMatch
  439.                     && (worstHit != worstPossible)
  440.                     && ((acumulate * 100 / worstHit) < 99)
  441.                     && !hitArray[foundIndex].isMarked)
  442.                 {
  443.                 hitArray[foundIndex].isMarked = true;
  444.                 Rect tempRect = {0, 0, screenWidth, screenHeight};
  445.                 Point point = { vertical, horizontal };
  446.                 
  447.                 zoomList.push_back(ZoomRect(tempRect, point));
  448.                 
  449.                 #if 0
  450.                 ZoomRects(tempRect, point);
  451.                 #endif
  452.                 }
  453.                 
  454.             worstHit = 0;
  455.             for (int i = 0; i < 5; ++i)
  456.                 {
  457.                 if (hitArray[i].hitValue > worstHit)
  458.                     worstHit = hitArray[i].hitValue;
  459.                 }
  460.             }
  461.             
  462.         srcPtr += 1;
  463.         }
  464.     
  465.     // Clean up the scan
  466.     
  467.     for (int i = 0; i < (bufferSize - 1); ++i)
  468.         {
  469.         InvertOval(&rectBuffer[tailPos]);
  470.         if (++tailPos == bufferSize) tailPos = 0;
  471.         }
  472.         
  473.     // Finish the sound
  474.     }
  475.     {
  476.     PlaySound gunShots("\pGun Shots.aif");
  477.     
  478.     short width = StringWidth("\pTarget Acquired...");
  479.     MoveTo((screenWidth - width) / 2, 100);
  480.     DrawString("\pTarget Acquired...");
  481.  
  482.     std::sort(&hitArray[0], &hitArray[5]);
  483.     
  484.     short crossX = 0;
  485.     short crossY = 0;
  486.         
  487.     for (int i = 0; i < 5; ++i)
  488.         {
  489.         PenMode (srcXor);
  490.         PenSize (2, 2);
  491.         
  492.         short horizontal = hitArray[i].hitLoc.h;
  493.         short vertical = hitArray[i].hitLoc.v;
  494.         
  495.         if (i == 0)
  496.             {
  497.             // draw new
  498.             
  499.             MoveTo(crossX, 0);
  500.             LineTo(crossX, screenHeight);
  501.             MoveTo(0, crossY);
  502.             LineTo(screenWidth, crossY);
  503.             }
  504.             
  505.         int count = 0;
  506.             
  507.         while ((crossX != horizontal) || (crossY != vertical))
  508.             {
  509.             for (ZoomList::iterator iter(zoomList.begin());
  510.                     iter != zoomList.end();
  511.                     ++iter)
  512.                 {
  513.                 if ((*iter).NextRect()) zoomList.pop_back();
  514.                 }
  515.             
  516.             if ((++count & 0x00000007) == 0)
  517.                 {
  518.                 unsigned long temp;
  519.                 Delay (1, &temp);
  520.                 }
  521.             
  522.             if (crossX != horizontal)
  523.                 {
  524.                 // draw new
  525.                 short newCrossX = crossX + ((horizontal < crossX) ? -1 : 1);
  526.                 
  527.                 MoveTo(newCrossX, 0);
  528.                 LineTo(newCrossX, screenHeight);
  529.                 
  530.                 // erase old
  531.                 MoveTo(crossX, 0);
  532.                 LineTo(crossX, screenHeight);
  533.  
  534.                 crossX = newCrossX;
  535.                 }
  536.             
  537.             if (crossY != vertical)
  538.                 {
  539.                 // draw new
  540.                 short newCrossY = crossY + ((vertical < crossY) ? -1 : 1);
  541.                 
  542.                 MoveTo(0, newCrossY);
  543.                 LineTo(screenWidth, newCrossY);
  544.                 
  545.                 // erase old
  546.                 MoveTo(0, crossY);
  547.                 LineTo(screenWidth, crossY);
  548.                 
  549.                 crossY = newCrossY;
  550.                 }
  551.             }
  552.             
  553.         if ( (hitArray[i].hitValue < 3000000) || (i == 4))
  554.             {
  555.             // erase old
  556.             
  557.             MoveTo(crossX, 0);
  558.             LineTo(crossX, screenHeight);
  559.             MoveTo(0, crossY);
  560.             LineTo(screenWidth, crossY);
  561.             
  562.             Rect tempRect = {0, 0, screenWidth, screenHeight};
  563.             Point point = { hitArray[i].hitLoc.v, hitArray[i].hitLoc.h };
  564.             
  565.             ZoomRects(tempRect, point);
  566.             
  567.             Rect rect;
  568.             rect.top = hitArray[i].hitLoc.v - 10;
  569.             rect.left = hitArray[i].hitLoc.h - 10;
  570.             rect.bottom = rect.top + 20;
  571.             rect.right = rect.left + 20;
  572.             
  573.             PenMode(subPin);
  574.             RGBColor color = { 0, 0xFFFF, 0xFFFF };
  575.             RGBForeColor(&color);
  576.             PaintOval(&rect);
  577.                 {
  578.                 // Reset the forecolor
  579.                 RGBColor color = { 0, 0, 0 };
  580.                 RGBForeColor(&color);
  581.                 }
  582.             PenNormal();
  583.             
  584.             if (i != 4)
  585.                 {
  586.                 // Draw Again
  587.                 
  588.                 PenMode (srcXor);
  589.                 PenSize (2, 2);
  590.             
  591.                 MoveTo(crossX, 0);
  592.                 LineTo(crossX, screenHeight);
  593.                 MoveTo(0, crossY);
  594.                 LineTo(screenWidth, crossY);
  595.                 }
  596.                 
  597.             *outPoints++ = hitArray[i].hitLoc;
  598.             (*outCount)++;
  599.             }
  600.         
  601.         }
  602.     
  603.     {
  604.     short width = StringWidth("\pTarget Acquired...");
  605.     MoveTo((screenWidth - width) / 2, 100);
  606.     DrawString("\pTarget Acquired...");
  607.     }
  608.     
  609.     unsigned long temp;
  610.     Delay(60, &temp);
  611.     PenNormal();
  612.     
  613.     // Finish the sound
  614.     }
  615.         
  616.     // Clean-up the GWorld
  617.     
  618.     CloseCPort(&port);
  619.     DisposeGWorld(world);
  620.     
  621.     SetGWorld(oldWorld, oldDevice);
  622.     
  623.     }
  624.  
  625.  
  626.